package com.tencent.albert.weixin.driver.utils;

import com.google.gson.Gson;
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.JsonNode;
import com.mashape.unirest.http.Unirest;
import com.mashape.unirest.http.exceptions.UnirestException;
import com.tencent.albert.spring.utils.Encodes;
import com.tencent.albert.weixin.driver.MsgManager;
import com.tencent.albert.weixin.driver.Constants;
import com.tencent.albert.weixin.driver.bean.*;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by albertzhu on 15/2/12.
 */
public class WeixinUtil {

    private static Logger logger = LoggerFactory.getLogger(WeixinUtil.class);
    private static final String WX_TOKEN_URL = "http://pmsshow:14449/pmsshow/wx/getWxtoken";
    /**
     * 验证签名
     *
     * @param signature
     * @param timestamp
     * @param nonce
     * @return
     */
    public static boolean checkSignature(String signature, String timestamp, String nonce) {
        String[] arr = new String[]{Constants.token, timestamp, nonce};
        // 将token、timestamp、nonce三个参数进行字典序排序
        Arrays.sort(arr);
        StringBuilder content = new StringBuilder();
        for (int i = 0; i < arr.length; i++) {
            content.append(arr[i]);
        }
        MessageDigest md = null;
        String tmpStr = null;

        try {
            md = MessageDigest.getInstance("SHA-1");
            // 将三个参数字符串拼接成一个字符串进行sha1加密
            byte[] digest = md.digest(content.toString().getBytes());
            tmpStr = Util.byteToStr(digest);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }

        content = null;
        // 将sha1加密后的字符串可与signature对比，标识该请求来源于微信
        return tmpStr != null ? tmpStr.equals(signature.toUpperCase()) : false;
    }

    public static String getOpenId(String code) {
        UserInfoAccessToken token = getUserInfoAccessToken(code,Constants.appId,Constants.appSecret);
        if (null != token) {
            return token.getOpenid();
        }
        return null;
    }

    public static WxUserInfo getWxUserInfo(String code) {
        UserInfoAccessToken token = getUserInfoAccessToken(code,Constants.appId,Constants.appSecret);
        if (null != token) {
            String requestUrl = Constants.user_info_url.replace("OPENID", token.getOpenid()).replace("ACCESS_TOKEN", token.getAccess_token());
            String temp = HttpUtil.readRespByGet(requestUrl, "GET", null);
            Gson gson = new Gson();
            WxUserInfo wxUserInfo = null;
            try {
                wxUserInfo = gson.fromJson(temp,WxUserInfo.class);
                if ( wxUserInfo.getErrcode() != 0 ) {
                    logger.info("get userInfo errcode:" + wxUserInfo.getErrcode()
                            + " errmsg:" + wxUserInfo.getErrmsg());
                    wxUserInfo = null;
                } else {
                    logger.debug( "get userInfo succ:" + wxUserInfo);
                }
            } catch (Exception e) {
                logger.info("get userInfo error "+e,e);
            }
            return wxUserInfo;
        }
        return null;
    }

    public static UserInfoAccessToken getUserInfoAccessToken(String code,String appid, String appsecret) {
        String requestUrl = Constants.user_info_access_token_url.replace("CODE", code).replace("APPID", appid).replace(
                "APPSECRET", appsecret);
        String temp = HttpUtil.readRespByGet(requestUrl, "GET", null);
        Gson gson = new Gson();
        UserInfoAccessToken accessToken = null;
        try {
            accessToken = gson.fromJson(temp,UserInfoAccessToken.class);
            if ( accessToken.getErrcode() != 0 ) {
                logger.info("get userInfo token errcode:" + accessToken.getErrcode()
                        + " errmsg:" + accessToken.getErrmsg());
                accessToken = null;
            } else {
                logger.debug( "get userInfo token succ:" + accessToken.getAccess_token());
            }
        } catch (Exception e) {
            logger.info("get userInfo token error "+e,e);
        }
        return accessToken;
    }

    /**
     * 获取access_token
     *
     * @param appid     凭证
     * @param appsecret 密钥
     * @return
     */
    public static AccessToken getAccessToken(String appid, String appsecret){
//        String requestUrl = Constants.access_token_url.replace("APPID", appid).replace("APPSECRET", appsecret);
//        String temp = HttpUtil.readRespByGet(requestUrl, "GET", null);
        AccessToken accessToken = null;
        try {
            HttpResponse<String> result = Unirest.get(WX_TOKEN_URL).asString();
            Gson gson = new Gson();

            accessToken = gson.fromJson(result.getBody(),AccessToken.class);
            if ( accessToken.getErrcode() != 0 ) {
                logger.info("get token errcode:" + accessToken.getErrcode()
                        + " errmsg:" + accessToken.getErrmsg());
                accessToken = null;
            } else {
                logger.debug( "get token succ:");
            }
        } catch (Exception e) {
            logger.info("get token error "+e,e);
        }
        return accessToken;
    }

    public static int delMenu(String accessToken) {
        int result = 0;

        // 拼装创建菜单的url
        String requestUrl = Constants.menu_del_url.replace("ACCESS_TOKEN", accessToken);

        String temp = HttpUtil.readRespByGet(requestUrl, "GET", null);
        Gson gson = new Gson();
        WxRespBean wxRespBean = null;
        try {
            wxRespBean = gson.fromJson(temp,WxRespBean.class);
            if ( wxRespBean.getErrcode() != 0 ) {
                logger.info("createMenu errcode:" + wxRespBean.getErrcode()
                        + " errmsg:" + wxRespBean.getErrmsg());
            }
        } catch (Exception e) {
            logger.info("createMenu error "+e,e);
        }
        return result;
    }


    /**
     * 创建菜单
     *
     * @param menu        菜单实例
     * @param accessToken 有效的access_token
     * @return 0表示成功，其他值表示失败
     */
    public static int createMenu(Menu menu, String accessToken) {
        // 拼装创建菜单的url
        String requestUrl = Constants.menu_create_url.replace("ACCESS_TOKEN", accessToken);
        // 将菜单对象转换成json字符串
        Gson gson = new Gson();
        String jsonMenu = null;
        try {
            byte[] jsonMenuBytes = gson.toJson(menu).getBytes("utf-8");
            System.out.println(jsonMenuBytes);
            jsonMenu = new String(jsonMenuBytes);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        System.out.println(jsonMenu);
        // 调用接口创建菜单
        String temp = HttpUtil.readRespByGet(requestUrl, "POST", jsonMenu);
        gson = new Gson();
        WxRespBean wxRespBean = null;
        try {
            wxRespBean = gson.fromJson(temp,WxRespBean.class);
            if ( wxRespBean.getErrcode() != 0 ) {
                logger.info("createMenu errcode:" + wxRespBean.getErrcode()
                        + " errmsg:" + wxRespBean.getErrmsg());
            } else {
                logger.info("createMenu succ.");
                return wxRespBean.getErrcode();
            }
        } catch (Exception e) {
            logger.info("createMenu error "+e,e);
        }
        return -1;
    }



    /**
     * 获取二维码ticket
     *
     * @param type        二维码类型 "" 临时二维码 | "limit" 永久二维码
     * @param accessToken 有效的access_token
     * @return 0表示成功，其他值表示失败
     */
    public static String getQrcodeTicket(String type, long expire_second, long scene_id,String scene_str, String accessToken) {


        Map<String,Object> map = new HashMap<String,Object>();

        Map<String,Object> scene = new HashMap<String,Object>();
        Map<String,Object> scene_id_map = new HashMap<String,Object>();

        scene_id_map.put("scene_id",scene_id);
        //scene_id_map.put("scene_str",scene_str);
        scene.put("scene",scene_id_map);
        map.put("action_info",scene);

        if(type.equals("limit")){
            map.put("action_name","QR_LIMIT_SCENE");
        }else{

            map.put("expire_seconds",expire_second);
            map.put("action_name","QR_SCENE");
        }
        String requestUrl = Constants.qrcode_create_url.replace("ACCESS_TOKEN", accessToken);

        Gson gson = new Gson();
        String jsonStr = null;
        try {
            byte[] jsonStrBytes = gson.toJson(map).getBytes("utf-8");
            jsonStr = new String(jsonStrBytes,"utf-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        System.out.println(jsonStr);
        // 调用接口拉取ticket
        Map<String,String> ticketMap = HttpUtil.httpRequest(requestUrl, "POST", jsonStr);
        return ticketMap.get("ticket");
    }


    public static String downMediaFile(String openId, String fileName,
                                       String mediaId) throws IOException {
        String mediaURL = Constants.mediaDownUrl + "access_token="
                + MsgManager.getAccessToken().getAccess_Token() + "&media_id=" + mediaId;
        return HttpUtil.downloadFile(openId, fileName, mediaURL,
                Constants.mediaBaseDic);
    }


    public static void sendRespMsg(SendMsgInfo info) {

        String temp = HttpUtil.readRespByGet(Constants.messgePostUrl
                + MsgManager.getAccessToken().getAccess_Token(), "POST", info.getContent());
        Gson gson = new Gson();
        WxRespBean wxRespBean = null;
        try {
            wxRespBean = gson.fromJson(temp,WxRespBean.class);
            if ( wxRespBean.getErrcode() != 0 ) {
                info.setError_code(wxRespBean.getErrcode());
                info.setError_msg(wxRespBean.getErrmsg());
                info.setStatus(Constants.MSG_STATUS_HANDLER);
                info.setSendTime(System.currentTimeMillis());
            }
        } catch (Exception e) {
            logger.info("sendRespMsg error "+e,e);
        }
//          info.setError_msg("Test not send");
//          info.setError_code(-100);
//          info.setStatus(Constants.MSG_STATUS_HANDLER_ERROR);
    }
}
